import os
import uuid
from datetime import datetime
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app, send_from_directory
from werkzeug.utils import secure_filename
from app.forms.user_forms import UserProfileForm, UserRegistrationForm, UserLoginForm, FileUploadForm, validate_avatar
from app.utils.response import response_success, response_fail
from app.models.user import User
from app.models.uploaded_file import UploadedFile
from app.utils.file_utils import FileUploadHandler
from app.extensions import db
from app.utils.jwt_utils import token_required
from functools import wraps

# 创建蓝图
profile_bp = Blueprint('profile', __name__, url_prefix='/profile')

# 允许的文件扩展名
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'webp'}

def allowed_file(filename):
    """检查文件扩展名是否被允许"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def save_uploaded_file(file, upload_folder, subfolder=''):
    """保存上传的文件并返回文件路径"""
    if file and allowed_file(file.filename):
        # 生成安全的文件名
        filename = secure_filename(file.filename)
        
        # 添加UUID前缀防止文件名冲突
        unique_filename = f"{uuid.uuid4().hex}_{filename}"
        
        # 创建子文件夹路径
        if subfolder:
            subfolder_path = os.path.join(upload_folder, subfolder)
            os.makedirs(subfolder_path, exist_ok=True)
            file_path = os.path.join(subfolder_path, unique_filename)
            relative_path = os.path.join(subfolder, unique_filename)
        else:
            os.makedirs(upload_folder, exist_ok=True)
            file_path = os.path.join(upload_folder, unique_filename)
            relative_path = unique_filename
        
        # 保存文件
        file.save(file_path)
        
        return relative_path
    
    return None

@profile_bp.route('/register', methods=['GET', 'POST'])
def register():
    """用户注册页面"""
    form = UserRegistrationForm()
    
    if form.validate_on_submit():
        # 处理表单提交
        username = form.username.data
        email = form.email.data
        password = form.password.data
        nickname = form.nickname.data
        
        # 检查用户名是否已存在
        if User.query.filter_by(username=username).first():
            flash('用户名已存在', 'error')
            return render_template('profile/register.html', form=form)
        
        # 检查邮箱是否已存在
        if User.query.filter_by(email=email).first():
            flash('邮箱已被注册', 'error')
            return render_template('profile/register.html', form=form)
        
        # 创建新用户
        user = User(
            username=username,
            email=email,
            nickname=nickname,
            created_at=datetime.utcnow()
        )
        user.set_password(password)
        
        # 保存到数据库
        db.session.add(user)
        db.session.commit()
        
        flash('注册成功！请登录', 'success')
        return redirect(url_for('profile.login'))
    
    return render_template('profile/register.html', form=form)

@profile_bp.route('/login', methods=['GET', 'POST'])
def login():
    """用户登录页面"""
    form = UserLoginForm()
    
    if form.validate_on_submit():
        # 处理表单提交
        username_or_email = form.username.data
        password = form.password.data
        remember_me = form.remember_me.data
        
        # 查找用户（通过用户名或邮箱）
        user = User.query.filter(
            (User.username == username_or_email) | 
            (User.email == username_or_email)
        ).first()
        
        # 验证用户和密码
        if user and user.check_password(password):
            # 登录成功，生成token
            from app.utils.jwt_utils import generate_tokens
            
            tokens = generate_tokens(user.id)
            
            flash('登录成功！', 'success')
            
            # 如果是AJAX请求，返回JSON
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify(response_success({
                'user': user.to_dict(),
                'tokens': tokens
            }, '登录成功'))
            
            # 否则重定向到个人资料页面
            return redirect(url_for('profile.dashboard'))
        else:
            flash('用户名或密码错误', 'error')
    
    return render_template('profile/login.html', form=form)

@profile_bp.route('/dashboard')
@token_required
def dashboard(current_user):
    """用户仪表板"""
    return render_template('profile/dashboard.html', user=current_user)

@profile_bp.route('/edit', methods=['GET', 'POST'])
@token_required
def edit_profile(current_user):
    """编辑用户资料"""
    form = UserProfileForm(obj=current_user)
    
    if form.validate_on_submit():
        try:
            # 更新用户基本信息
            current_user.username = form.username.data
            current_user.email = form.email.data
            current_user.nickname = form.nickname.data
            current_user.bio = form.bio.data
            current_user.age = form.age.data
            current_user.gender = form.gender.data
            current_user.phone = form.phone.data
            current_user.birth_date = form.birth_date.data
            current_user.address = form.address.data
            current_user.interests = form.interests.data
            current_user.website = form.website.data
            current_user.is_public = form.is_public.data
            current_user.updated_at = datetime.utcnow()
            
            # 处理头像上传
            if form.avatar.data:
                # 验证头像
                try:
                    validate_avatar(form, form.avatar)
                except ValueError as e:
                    flash(str(e), 'error')
                    return render_template('profile/edit.html', form=form, user=current_user)
                
                # 保存头像
                upload_folder = current_app.config.get('UPLOAD_FOLDER', 'uploads')
                avatar_path = save_uploaded_file(form.avatar.data, upload_folder, 'avatars')
                
                if avatar_path:
                    # 删除旧头像（如果存在）
                    if current_user.avatar:
                        old_avatar_path = os.path.join(upload_folder, current_user.avatar)
                        if os.path.exists(old_avatar_path):
                            os.remove(old_avatar_path)
                    
                    # 更新用户头像路径
                    current_user.avatar = avatar_path
                else:
                    flash('头像上传失败', 'error')
            
            # 保存到数据库
            db.session.commit()
            
            flash('个人资料更新成功！', 'success')
            
            # 如果是AJAX请求，返回JSON
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify(response_success(current_user.to_dict(), '个人资料更新成功'))
            
            return redirect(url_for('profile.view_profile', user_id=current_user.id))
            
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"更新用户资料失败: {str(e)}")
            flash('更新失败，请稍后再试', 'error')
    
    return render_template('profile/edit.html', form=form, user=current_user)

@profile_bp.route('/view/<int:user_id>')
def view_profile(user_id):
    """查看用户资料"""
    user = User.query.get_or_404(user_id)
    
    # 检查是否公开资料或当前用户查看自己的资料
    from flask_login import current_user
    if not user.is_public and (not current_user.is_authenticated or current_user.id != user.id):
        flash('该用户的资料未公开', 'error')
        return redirect(url_for('profile.dashboard'))
    
    return render_template('profile/view.html', user=user)

@profile_bp.route('/upload', methods=['GET', 'POST'])
@token_required
def upload_file(current_user):
    """文件上传页面"""
    form = FileUploadForm()
    
    if form.validate_on_submit():
        file = form.file.data
        description = form.description.data
        is_public = form.is_public.data
        
        if file:
            # 使用FileUploadHandler处理文件上传
            file_info, error = FileUploadHandler.save_file(file)
            
            if file_info:
                # 保存文件信息到数据库
                uploaded_file = UploadedFile(
                    filename=file_info['filename'],
                    original_filename=file_info['original_filename'],
                    file_path=file_info['file_path'],
                    relative_path=file_info['relative_path'],
                    file_size=file_info['file_size'],
                    content_type=file_info['content_type'],
                    category=file_info['category'],
                    description=description,
                    is_public=is_public,
                    user_id=current_user.id
                )
                
                db.session.add(uploaded_file)
                db.session.commit()
                
                flash('文件上传成功！', 'success')
                
                # 如果是AJAX请求，返回JSON
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return jsonify(response_success(uploaded_file.to_dict(), '文件上传成功'))
                
                return redirect(url_for('profile.upload_success', file_id=uploaded_file.id))
            else:
                flash(f'文件上传失败: {error}', 'error')
        else:
            flash('请选择要上传的文件', 'error')
    
    # 获取用户上传的文件列表
    files = UploadedFile.query.filter_by(user_id=current_user.id).order_by(UploadedFile.upload_time.desc()).limit(10).all()
    
    return render_template('profile/upload.html', form=form, files=files)

@profile_bp.route('/upload-success/<int:file_id>')
@token_required
def upload_success(current_user, file_id):
    """文件上传成功页面"""
    file = UploadedFile.query.filter_by(id=file_id, user_id=current_user.id).first_or_404()
    return render_template('profile/upload_success.html', file=file)

@profile_bp.route('/download/<int:file_id>')
@token_required
def download_file(current_user, file_id):
    """下载文件"""
    file = UploadedFile.query.get_or_404(file_id)
    
    # 检查权限：只有文件所有者或公开文件才能下载
    if file.user_id != current_user.id and not file.is_public:
        flash('没有权限下载此文件', 'error')
        return redirect(url_for('profile.dashboard'))
    
    # 检查文件是否存在
    if not os.path.exists(file.file_path):
        flash('文件不存在', 'error')
        return redirect(url_for('profile.dashboard'))
    
    return send_from_directory(
        os.path.dirname(file.file_path),
        os.path.basename(file.file_path),
        as_attachment=True,
        download_name=file.original_filename
    )

@profile_bp.route('/files/<int:file_id>', methods=['DELETE'])
@token_required
def delete_file(current_user, file_id):
    """删除文件"""
    file = UploadedFile.query.filter_by(id=file_id, user_id=current_user.id).first_or_404()
    
    try:
        # 删除物理文件
        success, message = FileUploadHandler.delete_file(file.file_path)
        
        if success:
            # 删除数据库记录
            db.session.delete(file)
            db.session.commit()
            
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify(response_success(None, '文件删除成功'))
            
            flash('文件删除成功', 'success')
        else:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify(response_fail(f'文件删除失败: {message}')), 400
            
            flash(f'文件删除失败: {message}', 'error')
    
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"删除文件失败: {str(e)}")
        
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return jsonify(response_fail('删除文件失败')), 500
        
        flash('删除文件失败', 'error')
    
    return redirect(url_for('profile.upload_file'))

@profile_bp.route('/files')
@token_required
def file_list(current_user):
    """文件列表页面"""
    page = request.args.get('page', 1, type=int)
    per_page = 20
    
    files = UploadedFile.query.filter_by(user_id=current_user.id).order_by(
        UploadedFile.upload_time.desc()
    ).paginate(page=page, per_page=per_page, error_out=False)
    
    return render_template('profile/files.html', files=files)

@profile_bp.route('/uploads/<path:filename>')
def uploaded_file(filename):
    """提供上传文件的访问"""
    upload_folder = current_app.config.get('UPLOAD_FOLDER', 'uploads')
    return send_from_directory(upload_folder, filename)

@profile_bp.route('/api/form-data', methods=['POST'])
def process_form_data():
    """处理表单数据的API端点"""
    try:
        # 获取表单数据
        form_data = request.form.to_dict()
        
        # 处理文件上传
        files = request.files.to_dict()
        uploaded_files = {}
        
        for field_name, file in files.items():
            if file and file.filename:
                upload_folder = current_app.config.get('UPLOAD_FOLDER', 'uploads')
                file_path = save_uploaded_file(file, upload_folder)
                if file_path:
                    uploaded_files[field_name] = file_path
        
        # 返回处理结果
        result = {
            'form_data': form_data,
            'uploaded_files': uploaded_files,
            'timestamp': datetime.utcnow().isoformat()
        }
        
        return jsonify(response_success(result, '表单数据处理成功'))
        
    except Exception as e:
        current_app.logger.error(f"处理表单数据失败: {str(e)}")
        return jsonify(response_fail('处理表单数据失败')), 500